/*
 * @Author: zdc 3215400595@qq.com
 * @Date: 2023-08-06 20:57:01
 * @LastEditors: zdc 3215400595@qq.com
 * @LastEditTime: 2023-08-06 23:16:46
 * @FilePath: /Logs_System/buffer.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
// 实现异步日志缓冲区

#ifndef _M_BUFFER_H__
#define _M_BUFFER_H__
#include <vector>
#include <cassert>
#include "util.hpp"
namespace tong_log
{
#define DEFAULT_BUFFER_SIZE (1 * 1024 * 2024)
#define THRESHOLD_BUFFER_SIZE (8 * 1024 * 1024)  // 扩容的阈值，小于阈值翻倍增长，达到线性增长
#define INCREAMENT_BUFFER_SIZE (1 * 1024 * 1024) // 扩容的线性增长
    class Buffer
    {
    public:
        Buffer() : _buffer(DEFAULT_BUFFER_SIZE), _reader_idx(0), _wirter_idx(0) {}

        void push(const char *data, size_t len) // 向缓冲区写入数据
        {
            // if (len > writeAbleSize())  // 缓冲区剩空间不够了 第一种方法 阻塞返回 false
            //     return;
            ensureEnoughSize(len); // 缓冲区剩空间不够了 第二种方法  扩容

            // 1.将数据拷贝到缓冲区
            std::copy(data, data + len, &_buffer[_wirter_idx]);
            // 2 将当前写入位置先后偏移
            moveWriter(len);
        }

        size_t writeAbleSize() // 返回可写数据的长度,对于扩容,不需要提供,因为永远可写.固定大小的缓冲区需要提供
        {
            return (_buffer.size() - _wirter_idx);
        }

        size_t readAbleSize() // 返回可读数据的长度
        {
            return (_wirter_idx - _reader_idx);
        }

        const char *begin() // 返回可读数据的起始地址
        {
            return &_buffer[_reader_idx];
        }

        void moveReader(size_t len) // 读指针进行向后偏移
        {
            assert(len <= readAbleSize());
            _reader_idx += len;
        }

        void reset() // 重置读写位置，初始化缓冲区
        {
            _reader_idx = 0; // 表示缓冲区所有空间都是空闲的
            _wirter_idx = 0; // 与_writer_idx相等表示没有数据可读
        }

        void swap(Buffer &buffer) // 对buffer空间实现交换操作
        {
            _buffer.swap(buffer._buffer);
            std::swap(_reader_idx, buffer._reader_idx);
            std::swap(_wirter_idx, buffer._wirter_idx);
        }

        bool empty() // 判断缓存区时候为空
        {
            return (_reader_idx == _wirter_idx);
        }

    private:
        void moveWriter(size_t len) // 将写指针向后偏移
        {
            assert((len + _wirter_idx) <= _buffer.size());
            _wirter_idx += len;
        }
        void ensureEnoughSize(size_t len) // 对空间进行扩容
        {
            if (len <= writeAbleSize())
                return;
            size_t newsize = 0;
            if (_buffer.size() < THRESHOLD_BUFFER_SIZE)
            {
                newsize = _buffer.size() * 2 + len; // 小于阈值 ，翻倍增长
            }
            else
            {
                newsize = _buffer.size() + INCREAMENT_BUFFER_SIZE + len; // 大于阈值，线性增长
            }
            _buffer.resize(newsize);
        }

    private:
        std::vector<char> _buffer;
        size_t _reader_idx; // 当前可读数据的指针（下标）
        size_t _wirter_idx; // 当前可写数据的指针
    };
}
#endif